package haust;

import java.nio.IntBuffer;
import java.util.ArrayList;

import org.lwjgl.BufferUtils;
import static org.lwjgl.openal.AL10.*;
import org.lwjgl.util.WaveData;

public class SoundManager {
	private static final String SOUNDPATH = "sounds/";
	private static ArrayList<SoundContainer> sounds = new ArrayList<SoundContainer>();
	private static ArrayList<SoundSource> sources = new ArrayList<SoundSource>();
	
	/**
	 * 
	 */
	public SoundManager() {	
	}
	
	/**
	 * Loads a .wav file in memory, and sends it to OpenAL.
	 * it will automatically look for the file in "sounds/" + soundName 
	 * @param soundName
	 * @return AL_TRUE on success, and AL_FALSE on fail
	 */
	public static int addSound(String soundName) {
		
		if(getSoundByName(soundName)!=null) 
			return AL_TRUE;
		
		/** Buffers hold sound data. */
		IntBuffer buffer = BufferUtils.createIntBuffer(1);

		// Load wav data into a buffer.
		alGenBuffers(buffer);

		if(alGetError() != AL_NO_ERROR)
			return AL_FALSE;
		
		//Loads the wave file from this class's package in your classpath
	    WaveData waveFile = WaveData.create(soundName);
	    
	    if( waveFile == null )
	    {
	    	System.out.println("Could not find sound: " + SOUNDPATH + soundName);
	    	return AL_FALSE;
	    }
	
	    alBufferData(buffer.get(0), waveFile.format, waveFile.data, waveFile.samplerate);
	    waveFile.dispose();
	    
	    sounds.add(new SoundContainer(buffer, soundName));
	    
	    return AL_TRUE;
	}
	
	/**
	 * 
	 * @param soundName
	 * @return The SoundContainer with the requested sound, or null on fail
	 */
	public static SoundContainer getSoundByName(String soundName){
		for(SoundContainer sc: sounds){
			if(sc.getSoundName().equalsIgnoreCase(soundName))
				return sc;
		}
		return null;
	}
	
	/**
	 * Searches through the cached sounds and creates a new OpenAL Sound source. 
	 * Default Values:
	 * AL_GAIN: 1.0f. 
	 * AL_PITCH: 1.0f.
	 * AL_SOURCE_RELATIVE: AL_FALSE
	 * @param soundName
	 * @return The new SoundSource or a blank SoundSource if requested file doesnt exist
	 */
	public static SoundSource createNewSource(String soundName)
	{
		SoundContainer sc = getSoundByName(soundName);
		
		if( sc == null )
		{
			System.out.println("Empty SoundSource created. Could not find sound: " + soundName);
			return new SoundSource();
		}
				
		IntBuffer sourceID = BufferUtils.createIntBuffer(1);
		alGenSources(sourceID);
		
		alSourcei(sourceID.get(0), AL_BUFFER, sc.getBufferId().get(0));
		alSourcef(sourceID.get(0), AL_GAIN, 1.0f);
		alSourcef(sourceID.get(0), AL_PITCH, 1.0f);
		alSourcei(sourceID.get(0), AL_SOURCE_RELATIVE, AL_FALSE);
		
		SoundSource sndSrc = new SoundSource(sourceID, new Vec3(), new Vec3() );
		
		sources.add(sndSrc);
		
		return sndSrc;
	}
	
	/**
	 * 
	 * @param src
	 */
	public static void removeSource( SoundSource src )
	{
		if( src == null )
			return;
		
		for( int i = 0; i < sources.size(); ++i )
		{
			if( sources.get(i).getSourceID() == src.getSourceID() )
			{
				sources.remove(i);
			}
		}
		
		alSourceStop(src.getSourceID());
		alDeleteSources(src.getSourceID());
	}
	
	/**
	 * Deletes all sources and buffers 
	 */
	public static void Destroy()
	{
		for( int i = 0; i < sources.size(); ++i )
		{
			alDeleteSources(sources.get(i).getSourceID());
		}
		sources.clear();
		
		for( int i = 0; i < sounds.size(); ++i )
		{
			alDeleteBuffers(sounds.get(i).getBufferId() );
		}
		sounds.clear();
	}
}
